Po przeczytaniu ukrytych funkcji i ciemnych rogów C ++ / STL na moderacji comp.lang.c ++. Byłem całkowicie zaskoczony, że następujący fragment został skompilowany i działał zarówno w Visual Studio 2008, jak i G ++ 4.4. Oto kod: #includeint main () { int x = 10; while (x -> 0) // x idzie do 0 { printf ("% d", x); } } Wynik: 9 8 7 6 5 4 3 2 1 0 Zakładam, że to jest C, ponieważ działa również w GCC. Gdzie jest to zdefiniowane w normie i skąd się wzięło?
2020-12-07 21:24:53
-> nie jest operatorem. W rzeczywistości są to dwa oddzielne operatory - i>. Kod warunku zmniejsza wartość x, zwracając oryginalną (nie zmniejszoną) wartość x, a następnie porównuje oryginalną wartość z 0 za pomocą operatora>. Aby lepiej zrozumieć, oświadczenie można zapisać w następujący sposób: podczas gdy ((x--)> 0) | Albo coś zupełnie innego ... x przesuwa się do 0. podczas gdy (x - \ \ \ \ > 0) printf ("% d", x); Nie tak matematycznie, ale ... każdy obraz to tysiąc słów ... | To bardzo skomplikowany operator, więc nawet ISO / IEC JTC1 (Wspólny Komitet Techniczny 1) umieścił swój opis w dwóch różnych częściach standardu C ++. Na marginesie, są to dwa różne operatory: - i> opisane odpowiednio w §5.2.6 / 2 i §5.9 standardu C ++ 03. | To odpowiednik podczas gdy (x--> 0) x-- (po zmniejszeniu) jest równoważne x = x-1, więc kod przekształca się w: while (x> 0) { x = x-1; // logika } x--; // Dekrementacja postu wykonana, gdy x <= 0 | x może dojść do zera jeszcze szybciej w przeciwnym kierunku: int x = 10; podczas gdy (0 <---- x) { printf ("% d", x); } 8 6 4 2 Możesz kontrolować prędkość za pomocą strzałki! int x = 100; podczas gdy (0 <-------------------- x) { printf ("% d", x); } 90 80 70 60 50 40 30 20 10 ;) | Jego #includeint main (void) { int x = 10; while (x--> 0) {// x idzie do 0 printf ("% d", x); } return 0; } Tylko przestrzeń sprawia, że rzeczy wyglądają śmiesznie, - zmniejsza się i> porównuje. | Użycie -> ma znaczenie historyczne. Zmniejszanie było (i nadal jest w niektórych przypadkach) szybsze niż zwiększanie w architekturze x86. Użycie -> sugeruje, że x zmierza do 0 i przemawia do osób z matematycznym doświadczeniem. | podczas gdy (x--> 0) jak to jest analizowane. | Całkowicie maniakiem, ale będę używał tego: #define as; while int main (int argc, char * argv []) { int n = atoi (argv [1]); do printf ("n to% d \ n", n) as (n -> 0); return 0; } | Jedna książka, którą przeczytałem (nie pamiętam dobrze, która książka) stwierdzała: Kompilatory próbują przeanalizować wyrażenia do największego tokenu, używając reguły lewej prawej. W tym przypadku wyrażenie: x -> 0 Analiza największych tokenów: żeton 1: x żeton 2: - token 3:> żeton 4: 0 wniosek: x--> 0 Ta sama zasada dotyczy tego wyrażenia: a ----- b Po przeanalizowaniu: żeton 1: a żeton 2: - żeton 3: - żeton 4: - żeton 5: b wniosek: (a -) - - b Mam nadzieję, że pomoże to zrozumieć skomplikowane wyrażenie ^^ | To jest dokładnie to samo co podczas gdy (x--) { printf ("% d", x); } dla liczb nieujemnych | W każdym razie mamy teraz operatora „idzie do”. „->” jest łatwy do zapamiętania jako kierunek, a „gdy x idzie do zera” oznacza proste. Co więcej, jest trochę bardziej wydajne niż „for (x = 10; x> 0; x -)” na niektórych platformach. | Ten kod najpierw porównuje x i 0, a następnie zmniejsza x. (Również powiedziane w pierwszej odpowiedzi: Post-dekrementujesz x, a następnie porównujesz x i 0 z operatorem>.) Zobacz wynik tego kodu: 9 8 7 6 5 4 3 2 1 0 Teraz najpierw porównujemy, a następnie zmniejszamy, widząc 0 na wyjściu. Jeśli chcemy najpierw zmniejszyć, a następnie porównać, użyj tego kodu: #include int main (nieważne) { int x = 10; while (--x> 0) // x idzie do 0 { printf ("% d", x); } return 0; } Ten wynik to: 9 8 7 6 5 4 3 2 1 | Mój kompilator wydrukuje 9876543210, kiedy uruchomię ten kod. #include int main () { int x = 10; while (x -> 0) // x idzie do 0 { std :: cout << x; } } Zgodnie z oczekiwaniami. While (x--> 0) w rzeczywistości oznacza while (x> 0). Dekrementacja x - post x. podczas gdy (x> 0) { x--; std :: cout << x; } to inny sposób pisania tej samej rzeczy. Fajnie, że oryginał wygląda jak „podczas gdy x idzie do 0”. | Brakuje spacji między - i>. x jest dekrementowany po sprawdzeniu warunku x> 0? | - jest operatorem dekrementacji, a> jest operatorem większości. Te dwa operatory są stosowane jako jeden, taki jak ->. | To połączenie dwóch operatorów. Pierwszy - służy do zmniejszania wartości, a> służy do sprawdzania, czy wartość jest większa niż argument po prawej stronie. #include int main () { int x = 10; podczas gdy (x--> 0) printf ("% d", x); return 0; } Wynik będzie: 9 8 7 6 5 4 3 2 1 0 | W rzeczywistości x jest post-dekrementacja i z tym warunkiem jest sprawdzany. To nie jest ->, to (x--)> 0 Uwaga: wartość x jest zmieniana po sprawdzeniu warunku, ponieważ następuje dekrementacja. Mogą również wystąpić podobne przypadki, na przykład: -> x -> 0 ++> x ++> 0 -> = x -> = 0 ++> = x ++> = 0 | C i C ++ przestrzegają zasady „maksymalnego munchu”. Tak samo jak a --- b jest tłumaczone na (a--) - b, w twoim przypadku x -> 0 przekłada się na (x -)> 0. Reguła mówi zasadniczo, że przechodząc od lewej do prawej, wyrażenia są tworzone przez przyjęcie maksymalnej liczby znaków, które utworzą prawidłowe wyrażenie. | Po co te wszystkie komplikacje? Prosta odpowiedź na pierwotne pytanie brzmi: #include int main () { int x = 10; podczas gdy (x>0) { printf ("% d", x); x = x-1; } } Robi to samo. Nie mówię, że powinieneś to zrobić w ten sposób, ale robi to samo i odpowiedziałby na pytanie w jednym poście. X-- jest po prostu skrótem powyższego, a> jest zwykłym operatorem większości. Żadnej wielkiej tajemnicy! W dzisiejszych czasach zbyt wielu ludzi komplikuje proste rzeczy;) | W konwencjonalny sposób zdefiniowalibyśmy warunek w nawiasach while pętli () i warunek kończący w nawiasach klamrowych {}, ale -> definiuje oba naraz. Na przykład: int abc (nieważne) { int a = 5 while ((a--)> 0) // Zmniejszenie i porównanie jednocześnie { // Kod } } To zmniejsza wartość a i uruchamia pętlę, gdy a jest większe niż 0. Konwencjonalnie byłoby tak: int abc (nieważne) { int a = 5; podczas gdy (a> 0) { za--; // Kod } za--; } W obie strony robimy to samo i osiągamy te same cele. | (x -> 0) oznacza (x--> 0). Możesz użyć (x ->) Wyjście: 9 8 7 6 5 4 3 2 1 0 Możesz użyć (- x> 0) To średnia (--x> 0) Wynik: 9 8 7 6 5 4 3 2 1 Możesz użyć (- \ \ x> 0) Wyjście: 9 8 7 6 5 4 3 2 1 Możesz użyć (\ \ x -> 0) Wyjście: 9 8 7 6 5 4 3 2 1 0 Możesz użyć (\ \ x -> 0 \ \ ) Wyjście: 9 8 7 6 5 4 3 2 1 0 Możesz też użyć ( x -> ) Wyjście: 9 8 7 6 5 4 3 2 1 0 Podobnie możesz wypróbować wiele metod, aby pomyślnie wykonać to polecenie. | Tutaj - jest jednoargumentowym operatorem dekrementacji postu. while (x--> 0) // x idzie do 0 { printf ("% d", x); } Na początku stan będzie oceniany jako (x> 0) // 10> 0 Teraz, ponieważ warunek jest prawdziwy, przejdzie do pętli ze zmniejszoną wartością x-- // x = 9 Dlatego pierwsza wydrukowana wartość to 9 I tak dalej. W ostatniej pętli x = 1, więc warunek jest prawdziwy. Zgodnie z operatorem jednoargumentowym wartość zmieniła się na x = 0 w momencie drukowania. Teraz x = 0, co oznacza, że warunek (x> 0) jest fałszywy, a pętla while kończy działanie. | To -> wcale nie jest operatorem. Mamy operator taki jak ->, ale nie taki jak ->. Jest to po prostu błędna interpretacja while (x--> 0), co oznacza po prostu, że x ma operator dekrementacji końcowej i ta pętla będzie działać, aż będzie większa od zera. Innym prostym sposobem napisania tego kodu byłoby while (x--). Pętla while zatrzyma się, gdy otrzyma fałszywy warunek, a tutaj jest tylko jeden przypadek, tj. 0. Więc zatrzyma się, gdy wartość x zostanie zmniejszona do zera. | Bardzo aktywne pytanie. Zdobądź 10 punktów reputacji, aby odpowiedzieć na to pytanie. Wymóg dotyczący reputacji pomaga chronić to pytanie przed spamem i brakiem odpowiedzi. Nie szukasz odpowiedzi? Przeglądaj inne pytania otagowane operatory c ++ c formatowanie kodu zgodność ze standardami lub zadaj własne pytanie.